<?php
declare(strict_types=1);

namespace Core\Package\Export;

use Core\HyperfUnit\Url;
use Exception;
use JetBrains\PhpStorm\ArrayShape;
use Zms\Unit\Directory;
use function Hyperf\Config\config;
use Swoole\Timer;

/**
 * 导出Excel
 */
class Excel
{
    const COLUMN_NAME = [
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ',
    ];

    public static function export(string $file, array $header, array $data): ?array
    {
        try {
            if (!preg_match('/(xls)/', $file)) {
                $file = $file . date("mdHis") . '.xlsx';//没有后缀自动添加后缀
            }
            //获取保存信息
            $save = self::getSaveInfo(config('server.settings.document_root') . '/export/' . date("Y-m") . '/' . $file);

            if (!is_dir($save['dir'])) {//目录不存在,先创建目录
                Directory::created($save['dir']);
            }
            //初始化组件
            $excel = new \Vtiful\Kernel\Excel(['path' => $save['dir']]);
            $excel->fileName($save['name'], 'sheet1')->setColumn('A1:B1', 500)->header($header)->data($data);
            //计算列数据
            $ColumnData = self::computeColumn($data, $header);
            foreach ($ColumnData as $index => $len) {
                $column_name = self::COLUMN_NAME[$index];
                $excel->setColumn("{$column_name}1:{$column_name}1", intval($len));
            }
            $filepath = $excel->output();
            $excel->close();
            return ['file' => $filepath, 'url' => Url::LocalFileToUrl($filepath)];
        } catch (Exception) {
            return null;
        }
    }


    #[
        ArrayShape(['dir' => 'string', 'name' => 'string', 'file' => 'string'])
    ]
    private static function getSaveInfo(string $file): array
    {
        $result = ['dir' => dirname($file) . '/', 'file' => $file];
        $result['name'] = mb_substr($file, mb_strlen($result['dir']) - mb_strlen($file)); // ing
        Timer::after(600000, function () use ($file) {
            @unlink($file);
        });
        return $result;
    }


    /**
     * 计算列宽
     * @param array $data
     * @param array $header
     * @return array
     */
    private static function computeColumn(array $data, array $header): array
    {
        $ColumnData = [];
        $data[] = $header;
        foreach ($data as $row) {
            foreach ($row as $index => $val) {
                if (!isset($ColumnData[$index])) {
                    $ColumnData[$index] = 0;
                }
                $ColumnData[$index] = max(strlen("{$val}"), $ColumnData[$index]);
            }
        }
        return $ColumnData;
    }
}